/**
 * NEURON IIoT System for Industry 4.0
 * Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 **/

/*
 * DO NOT EDIT THIS FILE MANUALLY!
 * It was automatically generated by `json-autotype`.
 */

 #include <stdlib.h>
 #include <string.h>
 
 #include <jansson.h>
 
 #include "json/json.h"
 
 #include "define.h"
 #include "msg.h"
 #include "tag.h"
 
 #include "json/neu_json_rw.h"
 #include "utils/hash_tag.h"
 
 int neu_json_encode_read_resp(void *json_object, void *param)
 {
     int                   ret  = 0;
     neu_json_read_resp_t *resp = (neu_json_read_resp_t *) param;
 
     void *                    tag_array = neu_json_array();
     neu_json_read_resp_tag_t *p_tag     = resp->tags;
     for (int i = 0; i < resp->n_tag; i++) {
         neu_json_elem_t tag_elems[2 + NEU_TAG_META_SIZE] = { 0 };
         int             if_precision                     = 0;
 
         tag_elems[0].name      = "name";
         tag_elems[0].t         = NEU_JSON_STR;
         tag_elems[0].v.val_str = p_tag->name;
 
         if (p_tag->error != 0) {
             tag_elems[1].name      = "error";
             tag_elems[1].t         = NEU_JSON_INT;
             tag_elems[1].v.val_int = p_tag->error;
         } else {
             tag_elems[1].name      = "value";
             tag_elems[1].t         = p_tag->t;
             tag_elems[1].v         = p_tag->value;
             tag_elems[1].precision = p_tag->precision;
             tag_elems[1].bias      = p_tag->datatag.bias;
 
             if (p_tag->t == NEU_JSON_FLOAT || p_tag->t == NEU_JSON_DOUBLE) {
                 if_precision      = 1;
                 tag_elems[2].name = "transferPrecision";
                 tag_elems[2].t    = NEU_JSON_INT;
                 tag_elems[2].v.val_int =
                     p_tag->precision > 0 ? p_tag->precision : 1;
             }
         }
 
         for (int k = 0; k < p_tag->n_meta; k++) {
             tag_elems[if_precision + 2 + k].name = p_tag->metas[k].name;
             tag_elems[if_precision + 2 + k].t    = p_tag->metas[k].t;
             tag_elems[if_precision + 2 + k].v    = p_tag->metas[k].value;
         }
 
         tag_array = neu_json_encode_array(tag_array, tag_elems,
                                           2 + if_precision + p_tag->n_meta);
         p_tag++;
     }
 
     neu_json_elem_t resp_elems[] = { {
         .name         = "tags",
         .t            = NEU_JSON_OBJECT,
         .v.val_object = tag_array,
     } };
     ret = neu_json_encode_field(json_object, resp_elems,
                                 NEU_JSON_ELEM_SIZE(resp_elems));
 
     return ret;
 }
 
 int neu_json_encode_read_paginate_resp(void *json_object, void *param)
 {
     int                            ret = 0;
     neu_json_read_paginate_resp_t *resp =
         (neu_json_read_paginate_resp_t *) param;
 
     void *                             tag_array = neu_json_array();
     neu_json_read_paginate_resp_tag_t *p_tag     = resp->tags;
 
     for (int i = 0; i < resp->n_tag; i++) {
         neu_json_elem_t tag_elems[10 + NEU_TAG_META_SIZE] = { 0 };
         int             if_precision                      = 0;
 
         tag_elems[0].name      = "name";
         tag_elems[0].t         = NEU_JSON_STR;
         tag_elems[0].v.val_str = p_tag->name;
 
         tag_elems[1].name      = "type";
         tag_elems[1].t         = NEU_JSON_INT;
         tag_elems[1].v.val_int = p_tag->datatag.type;
 
         tag_elems[2].name      = "address";
         tag_elems[2].t         = NEU_JSON_STR;
         tag_elems[2].v.val_str = p_tag->datatag.address;
 
         tag_elems[3].name      = "attribute";
         tag_elems[3].t         = NEU_JSON_INT;
         tag_elems[3].v.val_int = p_tag->datatag.attribute;
 
         tag_elems[4].name      = "description";
         tag_elems[4].t         = NEU_JSON_STR;
         tag_elems[4].v.val_str = p_tag->datatag.description;
 
         tag_elems[5].name      = "precision";
         tag_elems[5].t         = NEU_JSON_INT;
         tag_elems[5].v.val_int = p_tag->datatag.precision;
 
         tag_elems[6].name         = "decimal";
         tag_elems[6].t            = NEU_JSON_DOUBLE;
         tag_elems[6].v.val_double = p_tag->datatag.decimal;
 
         tag_elems[7].name         = "bias";
         tag_elems[7].t            = NEU_JSON_DOUBLE;
         tag_elems[7].v.val_double = p_tag->datatag.bias;
 
         if (p_tag->error != 0) {
             tag_elems[8].name      = "error";
             tag_elems[8].t         = NEU_JSON_INT;
             tag_elems[8].v.val_int = p_tag->error;
         } else {
             tag_elems[8].name      = "value";
             tag_elems[8].t         = p_tag->t;
             tag_elems[8].v         = p_tag->value;
             tag_elems[8].precision = p_tag->precision;
             tag_elems[8].bias      = p_tag->datatag.bias;
 
             if (p_tag->t == NEU_JSON_FLOAT || p_tag->t == NEU_JSON_DOUBLE) {
                 if_precision      = 1;
                 tag_elems[9].name = "transferPrecision";
                 tag_elems[9].t    = NEU_JSON_INT;
                 tag_elems[9].v.val_int =
                     p_tag->precision > 0 ? p_tag->precision : 1;
             }
         }
 
         for (int k = 0; k < p_tag->n_meta; k++) {
             tag_elems[if_precision + 9 + k].name = p_tag->metas[k].name;
             tag_elems[if_precision + 9 + k].t    = p_tag->metas[k].t;
             tag_elems[if_precision + 9 + k].v    = p_tag->metas[k].value;
         }
 
         tag_array = neu_json_encode_array(tag_array, tag_elems,
                                           9 + if_precision + p_tag->n_meta);
 
         free(p_tag->datatag.name);
         free(p_tag->datatag.address);
         free(p_tag->datatag.description);
 
         p_tag++;
     }
 
     void *          meta_object  = neu_json_encode_new();
     neu_json_elem_t meta_elems[] = {
         { .name      = "currentPage",
           .t         = NEU_JSON_INT,
           .v.val_int = resp->meta.current_page },
         { .name      = "pageSize",
           .t         = NEU_JSON_INT,
           .v.val_int = resp->meta.page_size },
         { .name = "total", .t = NEU_JSON_INT, .v.val_int = resp->meta.total }
     };
     neu_json_encode_field(meta_object, meta_elems, 3);
 
     neu_json_elem_t resp_elems[] = {
         { .name = "meta", .t = NEU_JSON_OBJECT, .v.val_object = meta_object },
         { .name = "items", .t = NEU_JSON_OBJECT, .v.val_object = tag_array },
     };
     ret = neu_json_encode_field(json_object, resp_elems, 2);
 
     return ret;
 }
 
 int neu_json_encode_test_read_tag_resp(void *json_object, void *param)
 {
     int                       ret       = 0;
     neu_resp_test_read_tag_t *resp      = (neu_resp_test_read_tag_t *) param;
     neu_json_elem_t           resp_elem = { 0 };
 
     if (resp->type == NEU_TYPE_ERROR) {
         resp_elem.name      = "error";
         resp_elem.t         = NEU_JSON_INT;
         resp_elem.v.val_int = resp->error;
     } else {
         resp_elem.name = "value";
         resp_elem.t    = resp->t;
         resp_elem.v    = resp->value;
     }
 
     ret = neu_json_encode_field(json_object, &resp_elem, 1);
 
     if (resp->t == NEU_JSON_STR) {
         free(resp->value.val_str);
     }
 
     return ret;
 }
 
 int neu_json_encode_read_resp1(void *json_object, void *param)
 {
     int                   ret  = 0;
     neu_json_read_resp_t *resp = (neu_json_read_resp_t *) param;
 
     void *values = neu_json_encode_new();
     void *errors = neu_json_encode_new();
     void *metas  = neu_json_encode_new();
 
     neu_json_read_resp_tag_t *p_tag = resp->tags;
     for (int i = 0; i < resp->n_tag; i++) {
         neu_json_elem_t tag_elem = { 0 };
 
         if (p_tag->error == 0) {
             tag_elem.name      = p_tag->name;
             tag_elem.t         = p_tag->t;
             tag_elem.v         = p_tag->value;
             tag_elem.precision = p_tag->precision;
             tag_elem.bias      = p_tag->datatag.bias;
             neu_json_encode_field(values, &tag_elem, 1);
         } else {
             tag_elem.name      = p_tag->name;
             tag_elem.t         = NEU_JSON_INT;
             tag_elem.v.val_int = p_tag->error;
             neu_json_encode_field(errors, &tag_elem, 1);
         }
 
         if (p_tag->n_meta > 0) {
             void *meta = neu_json_encode_new();
             for (int k = 0; k < p_tag->n_meta; k++) {
                 neu_json_elem_t meta_elem = { 0 };
                 meta_elem.name            = p_tag->metas[k].name;
                 meta_elem.t               = p_tag->metas[k].t;
                 meta_elem.v               = p_tag->metas[k].value;
                 neu_json_encode_field(meta, &meta_elem, 1);
             }
 
             neu_json_elem_t meta_elem = { 0 };
             meta_elem.name            = p_tag->name;
             meta_elem.t               = NEU_JSON_OBJECT;
             meta_elem.v.val_object    = meta;
             neu_json_encode_field(metas, &meta_elem, 1);
         }
 
         p_tag++;
     }
 
     neu_json_elem_t resp_elems[] = {
         {
             .name         = "values",
             .t            = NEU_JSON_OBJECT,
             .v.val_object = values,
         },
         {
             .name         = "errors",
             .t            = NEU_JSON_OBJECT,
             .v.val_object = errors,
 
         },
         {
             .name         = "metas",
             .t            = NEU_JSON_OBJECT,
             .v.val_object = metas,
 
         },
     };
 
     ret = neu_json_encode_field(json_object, resp_elems,
                                 NEU_JSON_ELEM_SIZE(resp_elems));
     return ret;
 }
 
 int neu_json_encode_read_resp2(void *json_object, void *param)
 {
     int                   ret  = 0;
     neu_json_read_resp_t *resp = (neu_json_read_resp_t *) param;
 
     void *                    tag_array = neu_json_array();
     neu_json_read_resp_tag_t *p_tag     = resp->tags;
     for (int i = 0; i < resp->n_tag; i++) {
         neu_json_elem_t tag_elems[2 + NEU_TAG_META_SIZE] = { 0 };
 
         tag_elems[0].name      = "name";
         tag_elems[0].t         = NEU_JSON_STR;
         tag_elems[0].v.val_str = p_tag->name;
 
         if (p_tag->error != 0) {
             tag_elems[1].name      = "error";
             tag_elems[1].t         = NEU_JSON_INT;
             tag_elems[1].v.val_int = p_tag->error;
         } else {
             tag_elems[1].name      = "value";
             tag_elems[1].t         = p_tag->t;
             tag_elems[1].v         = p_tag->value;
             tag_elems[1].precision = p_tag->precision;
         }
 
         for (int k = 0; k < p_tag->n_meta; k++) {
             tag_elems[2 + k].name = p_tag->metas[k].name;
             tag_elems[2 + k].t    = p_tag->metas[k].t;
             tag_elems[2 + k].v    = p_tag->metas[k].value;
         }
 
         tag_array =
             neu_json_encode_array(tag_array, tag_elems, 2 + p_tag->n_meta);
         p_tag++;
     }
 
     neu_json_elem_t resp_elems[] = { {
         .name         = "tags",
         .t            = NEU_JSON_OBJECT,
         .v.val_object = tag_array,
     } };
     ret = neu_json_encode_field(json_object, resp_elems,
                                 NEU_JSON_ELEM_SIZE(resp_elems));
 
     return ret;
 }
 
 int neu_json_decode_write_req(char *buf, neu_json_write_req_t **result)
 {
    printf("neu_json_decode_write_req\n");
     void *json_obj = neu_json_decode_new(buf);
     if (NULL == json_obj) {
         return -1;
     }
 
     int ret = neu_json_decode_write_req_json(json_obj, result);
     neu_json_decode_free(json_obj);
     return ret;
 }
 
//  {
//     "ver":"2.12",
//     "id": "221",
//     "name": "YYT3_TEST",
//     "val": "1237",
//     "timeout": "30",
//     "msg": "",
//     "time": "1565447542"
// }

int decode_write_req_json(void *json_obj, neu_json_write_req_t *req)
{
    int ret = 0;

    neu_json_elem_t req_elems[] = {
        {
            .name = "ver",
            .t    = NEU_JSON_STR,
        },
        {
            .name = "id",
            .t    = NEU_JSON_STR,
        },
        {
            .name = "name",
            .t    = NEU_JSON_STR,
        },
        {
            .name = "val",
            .t    = NEU_JSON_VALUE,
        },
        {
            .name = "tag",
            .t    = NEU_JSON_STR,
            .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL
        },
        {
            .name = "timeout",
            .t    = NEU_JSON_STR,
            .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL
        },
        {
            .name = "msg",
            .t    = NEU_JSON_STR,
            .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL
        },
        {
            .name = "time",
            .t    = NEU_JSON_STR,
            .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL
        },
        {
            .name      = "precision",
            .t         = NEU_JSON_INT,
            .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
        },
    };

    ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems),
                                  req_elems);
    if (ret != 0) {
        goto error;
    }

    if (req_elems[8].v.val_int > 0) {
        req_elems[3].t            = NEU_JSON_DOUBLE;
        req_elems[3].v.val_double = (double_t) req_elems[3].v.val_int;
    }

    req->node  = req_elems[2].v.val_str;
    req->group = req_elems[1].v.val_str;
    // req->tag   = req_elems[4].v.val_str;
    // req->tag   = req_elems[4].v.val_str; //这里后续需要构建name和val对应的寄存器,注意这里必须是动态内存，后续有释放动作->handle_write
    // req->t     = req_elems[3].t;
    req->value = req_elems[3].v;

    req->ver=req_elems[0].v.val_str;
    char val_buffer[48]={0};
    if (req_elems[3].t == NEU_JSON_INT) {
        // 整型转字符串
        snprintf(val_buffer, sizeof(val_buffer), "%lld" , req_elems[3].v.val_int);
        req->val = strdup(val_buffer);
    } 
    else if(req_elems[3].t == NEU_JSON_STR)
        req->val=req_elems[3].v.val_str;

    // 新增映射查询
    NodeValMapping* mapping = find_mapping(req->node, req->val);
    if (mapping) {
        req->tag = strdup(mapping->tag); // 动态拷贝tag
        req->t     = mapping->t; // 在哈希结构中设定写入寄存器值的类型
        req->value = mapping->write_num; 
    } else {
        // 处理未找到的情况
        req->tag = NULL;
        req->t=req_elems[3].t;
    }
    return ret;

error:
    free(req_elems[0].v.val_str);
    free(req_elems[1].v.val_str);
    free(req_elems[2].v.val_str);
    free(req_elems[4].v.val_str);
    if (req->val) free(req->val);  // 释放可能已分配的val内存
    return ret;
}

//  int decode_write_req_json(void *json_obj, neu_json_write_req_t *req)
//  {
//      int ret = 0;
 
//      neu_json_elem_t req_elems[] = {
//          {
//              .name = "node",
//              .t    = NEU_JSON_STR,
//          },
//          {
//              .name = "group",
//              .t    = NEU_JSON_STR,
//          },
//          {
//              .name = "tag",
//              .t    = NEU_JSON_STR,
//          },
//          {
//              .name = "value",
//              .t    = NEU_JSON_VALUE,
//          },
//          {
//              .name      = "precision",
//              .t         = NEU_JSON_INT,
//              .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
//          },
//      };
 
//      ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems),
//                                    req_elems);
//      if (ret != 0) {
//          goto error;
//      }
 
//      if (req_elems[4].v.val_int > 0) {
//          req_elems[3].t            = NEU_JSON_DOUBLE;
//          req_elems[3].v.val_double = (double_t) req_elems[3].v.val_int;
//      }
 
//      req->node  = req_elems[0].v.val_str;
//      req->group = req_elems[1].v.val_str;
//      req->tag   = req_elems[2].v.val_str;
//      req->t     = req_elems[3].t;
//      req->value = req_elems[3].v;
 
//      return ret;
 
//  error:
//      free(req_elems[0].v.val_str);
//      free(req_elems[1].v.val_str);
//      free(req_elems[2].v.val_str);
//      return ret;
//  }
 
 int neu_json_decode_write_req_json(void *                 json_obj,
                                    neu_json_write_req_t **result)
 {
     neu_json_write_req_t *req = calloc(1, sizeof(neu_json_write_req_t));
     if (req == NULL) {
         return -1;
     }
 
     int ret = decode_write_req_json(json_obj, req);
     if (0 == ret) {
         *result = req;
     } else {
         free(req);
     }
 
     return ret;
 }
 
 void neu_json_decode_write_req_free(neu_json_write_req_t *req)
 {
     free(req->group);
     free(req->node);
     free(req->tag);
     if (req->t == NEU_JSON_STR) {
         free(req->value.val_str);
     }
     if (req->t == NEU_JSON_ARRAY_INT8 && req->value.val_array_int8.length > 0) {
         free(req->value.val_array_int8.i8s);
     }
     if (req->t == NEU_JSON_ARRAY_UINT8 &&
         req->value.val_array_uint8.length > 0) {
         free(req->value.val_array_uint8.u8s);
     }
     if (req->t == NEU_JSON_ARRAY_INT16 &&
         req->value.val_array_int16.length > 0) {
         free(req->value.val_array_int16.i16s);
     }
     if (req->t == NEU_JSON_ARRAY_UINT16 &&
         req->value.val_array_uint16.length > 0) {
         free(req->value.val_array_uint16.u16s);
     }
     if (req->t == NEU_JSON_ARRAY_INT32 &&
         req->value.val_array_int32.length > 0) {
         free(req->value.val_array_int32.i32s);
     }
     if (req->t == NEU_JSON_ARRAY_UINT32 &&
         req->value.val_array_uint32.length > 0) {
         free(req->value.val_array_uint32.u32s);
     }
     if (req->t == NEU_JSON_ARRAY_INT64 &&
         req->value.val_array_int64.length > 0) {
         free(req->value.val_array_int64.i64s);
     }
     if (req->t == NEU_JSON_ARRAY_UINT64 &&
         req->value.val_array_uint64.length > 0) {
         free(req->value.val_array_uint64.u64s);
     }
     if (req->t == NEU_JSON_ARRAY_FLOAT &&
         req->value.val_array_float.length > 0) {
         free(req->value.val_array_float.f32s);
     }
     if (req->t == NEU_JSON_ARRAY_DOUBLE &&
         req->value.val_array_double.length > 0) {
         free(req->value.val_array_double.f64s);
     }
     if (req->t == NEU_JSON_ARRAY_BOOL && req->value.val_array_bool.length > 0) {
         free(req->value.val_array_bool.bools);
     }
 
     free(req);
 }
 
 int neu_json_decode_write_tags_req(char *                      buf,
                                    neu_json_write_tags_req_t **result)
 {
     void *json_obj = neu_json_decode_new(buf);
     if (NULL == json_obj) {
         return -1;
     }
 
     int ret = neu_json_decode_write_tags_req_json(json_obj, result);
     neu_json_decode_free(json_obj);
     return ret;
 }
 
 static int decode_write_tags_req_json(void *                     json_obj,
                                       neu_json_write_tags_req_t *req)
 {
     int ret = 0;
 
     neu_json_elem_t req_elems[] = {
         {
             .name = "node",
             .t    = NEU_JSON_STR,
         },
         {
             .name = "group",
             .t    = NEU_JSON_STR,
         },
         {
             .name = "tags",
             .t    = NEU_JSON_OBJECT,
         },
     };
     ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems),
                                   req_elems);
     if (ret != 0) {
         return -1;
     }
 
     req->node  = req_elems[0].v.val_str;
     req->group = req_elems[1].v.val_str;
 
     req->n_tag = neu_json_decode_array_size_by_json(json_obj, "tags");
     if (req->n_tag <= 0) {
         return -1;
     }
 
     req->tags = calloc(req->n_tag, sizeof(neu_json_write_tags_elem_t));
     for (int i = 0; i < req->n_tag; i++) {
         neu_json_elem_t v_elems[] = {
             {
                 .name = "tag",
                 .t    = NEU_JSON_STR,
             },
             {
                 .name = "value",
                 .t    = NEU_JSON_VALUE,
             },
         };
 
         ret = neu_json_decode_array_by_json(
             json_obj, "tags", i, NEU_JSON_ELEM_SIZE(v_elems), v_elems);
         req->tags[i].tag   = v_elems[0].v.val_str;
         req->tags[i].t     = v_elems[1].t;
         req->tags[i].value = v_elems[1].v;
 
         if (ret != 0) {
             for (; i >= 0; --i) {
                 free(req->tags[i].tag);
                 if (NEU_JSON_STR == req->tags[i].t) {
                     free(req->tags[i].value.val_str);
                 }
             }
             free(req->node);
             free(req->group);
             free(req->tags);
             req->tags = NULL;
             return ret;
         }
     }
 
     return 0;
 }
 
 int neu_json_decode_write_tags_req_json(void *                      json_obj,
                                         neu_json_write_tags_req_t **result)
 {
     neu_json_write_tags_req_t *req =
         calloc(1, sizeof(neu_json_write_tags_req_t));
     if (req == NULL) {
         return -1;
     }
 
     int ret = decode_write_tags_req_json(json_obj, req);
     if (0 == ret) {
         *result = req;
     } else {
         free(req);
     }
 
     return ret;
 }
 
 void neu_json_decode_write_tags_req_free(neu_json_write_tags_req_t *req)
 {
     free(req->group);
     free(req->node);
 
     for (int i = 0; i < req->n_tag; i++) {
         free(req->tags[i].tag);
         if (req->tags[i].t == NEU_JSON_STR) {
             free(req->tags[i].value.val_str);
         }
         if (req->tags[i].t == NEU_JSON_ARRAY_INT8 &&
             req->tags[i].value.val_array_int8.length > 0) {
             free(req->tags[i].value.val_array_int8.i8s);
         }
         if (req->tags[i].t == NEU_JSON_ARRAY_UINT8 &&
             req->tags[i].value.val_array_uint8.length > 0) {
             free(req->tags[i].value.val_array_uint8.u8s);
         }
         if (req->tags[i].t == NEU_JSON_ARRAY_INT16 &&
             req->tags[i].value.val_array_int16.length > 0) {
             free(req->tags[i].value.val_array_int16.i16s);
         }
         if (req->tags[i].t == NEU_JSON_ARRAY_UINT16 &&
             req->tags[i].value.val_array_uint16.length > 0) {
             free(req->tags[i].value.val_array_uint16.u16s);
         }
         if (req->tags[i].t == NEU_JSON_ARRAY_INT32 &&
             req->tags[i].value.val_array_int32.length > 0) {
             free(req->tags[i].value.val_array_int32.i32s);
         }
         if (req->tags[i].t == NEU_JSON_ARRAY_UINT32 &&
             req->tags[i].value.val_array_uint32.length > 0) {
             free(req->tags[i].value.val_array_uint32.u32s);
         }
         if (req->tags[i].t == NEU_JSON_ARRAY_INT64 &&
             req->tags[i].value.val_array_int64.length > 0) {
             free(req->tags[i].value.val_array_int64.i64s);
         }
         if (req->tags[i].t == NEU_JSON_ARRAY_UINT64 &&
             req->tags[i].value.val_array_uint64.length > 0) {
             free(req->tags[i].value.val_array_uint64.u64s);
         }
         if (req->tags[i].t == NEU_JSON_ARRAY_FLOAT &&
             req->tags[i].value.val_array_float.length > 0) {
             free(req->tags[i].value.val_array_float.f32s);
         }
         if (req->tags[i].t == NEU_JSON_ARRAY_DOUBLE &&
             req->tags[i].value.val_array_double.length > 0) {
             free(req->tags[i].value.val_array_double.f64s);
         }
         if (req->tags[i].t == NEU_JSON_ARRAY_BOOL &&
             req->tags[i].value.val_array_bool.length > 0) {
             free(req->tags[i].value.val_array_bool.bools);
         }
     }
     free(req->tags);
     free(req);
 }
 
 int neu_json_decode_write(char *buf, neu_json_write_t **result)
 {
     neu_json_write_t *req = calloc(1, sizeof(*req));
     if (NULL == req) {
         return -1;
     }
 
     void *json_obj = neu_json_decode_new(buf);
     if (NULL == json_obj) {
         free(req);
         return -1;
     }
 
     int ret = 0;
     if (NULL == json_object_get(json_obj, "tags")) {
         req->singular = true;
         ret           = decode_write_req_json(json_obj, &req->single);
     } else {
         req->singular = false;
         ret           = decode_write_tags_req_json(json_obj, &req->plural);
     }
 
     if (0 == ret) {
         *result = req;
     } else {
         free(req);
     }
 
     neu_json_decode_free(json_obj);
     return ret;
 }
 
 void neu_json_decode_write_free(neu_json_write_t *req)
 {
     if (req) {
         if (req->singular) {
             neu_json_decode_write_req_free((neu_json_write_req_t *) req);
         } else {
             neu_json_decode_write_tags_req_free(
                 (neu_json_write_tags_req_t *) req);
         }
     }
 }
 
 int neu_json_decode_read_req(char *buf, neu_json_read_req_t **result)
 {
     int   ret      = 0;
     void *json_obj = NULL;
 
     json_obj = neu_json_decode_new(buf);
     if (NULL == json_obj) {
         return -1;
     }
 
     neu_json_read_req_t *req = calloc(1, sizeof(neu_json_read_req_t));
     if (req == NULL) {
         neu_json_decode_free(json_obj);
         return -1;
     }
 
     neu_json_elem_t req_elems[] = {
         {
             .name = "node",
             .t    = NEU_JSON_STR,
         },
         {
             .name = "group",
             .t    = NEU_JSON_STR,
         },
         {
             .name      = "sync",
             .t         = NEU_JSON_BOOL,
             .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
         },
         {
             .name      = "query",
             .t         = NEU_JSON_OBJECT,
             .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
         },
     };
 
     neu_json_elem_t query_elems[] = {
         {
             .name      = "name",
             .t         = NEU_JSON_STR,
             .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
         },
         {
             .name      = "description",
             .t         = NEU_JSON_STR,
             .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
         },
     };
 
     ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems),
                                   req_elems);
     if (ret != 0) {
         goto error;
     }
 
     req->node  = req_elems[0].v.val_str;
     req->group = req_elems[1].v.val_str;
     req->sync  = req_elems[2].v.val_bool;
 
     if (req_elems[3].v.val_object) {
         ret = neu_json_decode_by_json(req_elems[3].v.val_object,
                                       NEU_JSON_ELEM_SIZE(query_elems),
                                       query_elems);
         if (ret != 0) {
             goto error;
         }
         req->name = query_elems[0].v.val_str;
         req->desc = query_elems[1].v.val_str;
     }
 
     *result = req;
     neu_json_decode_free(json_obj);
     return ret;
 
 error:
     free(query_elems[0].v.val_str);
     free(query_elems[1].v.val_str);
     free(req_elems[0].v.val_str);
     free(req_elems[1].v.val_str);
     free(req);
     if (json_obj != NULL) {
         neu_json_decode_free(json_obj);
     }
     return ret;
 }
 
 void neu_json_decode_read_req_free(neu_json_read_req_t *req)
 {
     free(req->group);
     free(req->node);
 
     free(req);
 }
 
 int neu_json_decode_read_paginate_req(char *                         buf,
                                       neu_json_read_paginate_req_t **result)
 {
     int   ret      = 0;
     void *json_obj = NULL;
 
     json_obj = neu_json_decode_new(buf);
     if (NULL == json_obj) {
         return -1;
     }
 
     neu_json_read_paginate_req_t *req =
         calloc(1, sizeof(neu_json_read_paginate_req_t));
     if (req == NULL) {
         neu_json_decode_free(json_obj);
         return -1;
     }
 
     neu_json_elem_t req_elems[] = {
         {
             .name = "node",
             .t    = NEU_JSON_STR,
         },
         {
             .name = "group",
             .t    = NEU_JSON_STR,
         },
         {
             .name      = "sync",
             .t         = NEU_JSON_BOOL,
             .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
         },
         {
             .name      = "query",
             .t         = NEU_JSON_OBJECT,
             .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
         },
     };
 
     neu_json_elem_t query_elems[] = {
         {
             .name      = "name",
             .t         = NEU_JSON_STR,
             .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
         },
         {
             .name      = "description",
             .t         = NEU_JSON_STR,
             .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
         },
         {
             .name      = "currentPage",
             .t         = NEU_JSON_INT,
             .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
         },
         {
             .name      = "pageSize",
             .t         = NEU_JSON_INT,
             .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
         },
         {
             .name      = "isError",
             .t         = NEU_JSON_BOOL,
             .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
         },
     };
 
     ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems),
                                   req_elems);
 
     if (ret != 0) {
         goto error;
     }
 
     req->node  = req_elems[0].v.val_str;
     req->group = req_elems[1].v.val_str;
     req->sync  = req_elems[2].v.val_bool;
 
     if (req_elems[3].v.val_object) {
         ret = neu_json_decode_by_json(req_elems[3].v.val_object,
                                       NEU_JSON_ELEM_SIZE(query_elems),
                                       query_elems);
 
         if (ret != 0) {
             goto error;
         }
         req->name         = query_elems[0].v.val_str;
         req->desc         = query_elems[1].v.val_str;
         req->current_page = query_elems[2].v.val_int;
         req->page_size    = query_elems[3].v.val_int;
         req->is_error     = query_elems[4].v.val_bool;
     }
 
     *result = req;
     neu_json_decode_free(json_obj);
     return ret;
 
 error:
     free(query_elems[0].v.val_str);
     free(query_elems[1].v.val_str);
     free(req_elems[0].v.val_str);
     free(req_elems[1].v.val_str);
     free(req);
     if (json_obj != NULL) {
         neu_json_decode_free(json_obj);
     }
     return ret;
 }
 
 void neu_json_decode_read_paginate_req_free(neu_json_read_paginate_req_t *req)
 {
     free(req->group);
     free(req->node);
 
     free(req);
 }
 
 int neu_json_decode_test_read_tag_req(char *                         buf,
                                       neu_json_test_read_tag_req_t **result)
 {
     int                           ret      = 0;
     void *                        json_obj = NULL;
     neu_json_test_read_tag_req_t *req =
         calloc(1, sizeof(neu_json_test_read_tag_req_t));
     if (req == NULL) {
         return -1;
     }
 
     json_obj = neu_json_decode_new(buf);
     if (NULL == json_obj) {
         free(req);
         return -1;
     }
 
     neu_json_elem_t req_elems[] = {
         {
             .name = "driver",
             .t    = NEU_JSON_STR,
         },
         {
             .name = "group",
             .t    = NEU_JSON_STR,
         },
         {
             .name = "tag",
             .t    = NEU_JSON_STR,
         },
         {
             .name = "address",
             .t    = NEU_JSON_STR,
         },
         {
             .name = "attribute",
             .t    = NEU_JSON_INT,
         },
         {
             .name = "type",
             .t    = NEU_JSON_INT,
         },
         {
             .name = "precision",
             .t    = NEU_JSON_INT,
         },
         {
             .name = "decimal",
             .t    = NEU_JSON_DOUBLE,
         },
         {
             .name = "bias",
             .t    = NEU_JSON_DOUBLE,
         },
     };
     ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems),
                                   req_elems);
     if (ret != 0) {
         goto decode_fail;
     }
 
     req->driver    = req_elems[0].v.val_str;
     req->group     = req_elems[1].v.val_str;
     req->tag       = req_elems[2].v.val_str;
     req->address   = req_elems[3].v.val_str;
     req->attribute = req_elems[4].v.val_int;
     req->type      = req_elems[5].v.val_int;
     req->precision = req_elems[6].v.val_int;
     req->decimal   = req_elems[7].v.val_double;
     req->bias      = req_elems[8].v.val_double;
     *result        = req;
     goto decode_exit;
 
 decode_fail:
     free(req);
     free(req_elems[0].v.val_str);
     free(req_elems[1].v.val_str);
     free(req_elems[2].v.val_str);
     free(req_elems[3].v.val_str);
     ret = -1;
 
 decode_exit:
     if (json_obj != NULL) {
         neu_json_decode_free(json_obj);
     }
     return ret;
 }
 
 void neu_json_decode_test_read_tag_req_free(neu_json_test_read_tag_req_t *req)
 {
     free(req->driver);
     free(req->group);
     free(req->tag);
     free(req->address);
     free(req);
 }
 
 int neu_json_encode_read_periodic_resp(void *json_object, void *param)
 {
     int                       ret  = 0;
     neu_json_read_periodic_t *resp = (neu_json_read_periodic_t *) param;
 
     neu_json_elem_t resp_elems[] = { {
                                          .name      = "node",
                                          .t         = NEU_JSON_STR,
                                          .v.val_str = resp->node,
                                      },
                                      {
                                          .name      = "group",
                                          .t         = NEU_JSON_STR,
                                          .v.val_str = resp->group,
                                      },
                                      {
                                          .name      = "timestamp",
                                          .t         = NEU_JSON_INT,
                                          .v.val_int = resp->timestamp,
                                      } };
     ret = neu_json_encode_field(json_object, resp_elems,
                                 NEU_JSON_ELEM_SIZE(resp_elems));
 
     return ret;
 }
 
 void neu_json_metas_to_json(neu_tag_meta_t *metas, int n_meta,
                             neu_json_read_resp_tag_t *json_tag)
 {
     for (int k = 0; k < n_meta; k++) {
         if (strlen(metas[k].name) > 0) {
             json_tag->metas[k].name = metas[k].name;
             switch (metas[k].value.type) {
             case NEU_TYPE_UINT8:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.u8;
                 break;
             case NEU_TYPE_INT8:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.i8;
                 break;
             case NEU_TYPE_INT16:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.i16;
                 break;
             case NEU_TYPE_INT32:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.i32;
                 break;
             case NEU_TYPE_INT64:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.i64;
                 break;
             case NEU_TYPE_WORD:
             case NEU_TYPE_UINT16:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.u16;
                 break;
             case NEU_TYPE_DWORD:
             case NEU_TYPE_UINT32:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.u32;
                 break;
             case NEU_TYPE_LWORD:
             case NEU_TYPE_UINT64:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.u64;
                 break;
             case NEU_TYPE_FLOAT:
                 json_tag->metas[k].t               = NEU_JSON_FLOAT;
                 json_tag->metas[k].value.val_float = metas[k].value.value.f32;
                 break;
             case NEU_TYPE_DOUBLE:
                 json_tag->metas[k].t                = NEU_JSON_DOUBLE;
                 json_tag->metas[k].value.val_double = metas[k].value.value.d64;
                 break;
             case NEU_TYPE_BOOL:
                 json_tag->metas[k].t = NEU_JSON_BOOL;
                 json_tag->metas[k].value.val_bool =
                     metas[k].value.value.boolean;
                 break;
             case NEU_TYPE_BIT:
                 json_tag->metas[k].t             = NEU_JSON_BIT;
                 json_tag->metas[k].value.val_bit = metas[k].value.value.u8;
                 break;
             case NEU_TYPE_STRING:
             case NEU_TYPE_TIME:
             case NEU_TYPE_DATA_AND_TIME:
                 json_tag->metas[k].t             = NEU_JSON_STR;
                 json_tag->metas[k].value.val_str = metas[k].value.value.str;
                 break;
             default:
                 break;
             }
         } else {
             break;
         }
     }
 }
 
 void neu_json_metas_to_json_paginate(
     neu_tag_meta_t *metas, int n_meta,
     neu_json_read_paginate_resp_tag_t *json_tag)
 {
     for (int k = 0; k < n_meta; k++) {
         if (strlen(metas[k].name) > 0) {
             json_tag->metas[k].name = metas[k].name;
             switch (metas[k].value.type) {
             case NEU_TYPE_UINT8:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.u8;
                 break;
             case NEU_TYPE_INT8:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.i8;
                 break;
             case NEU_TYPE_INT16:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.i16;
                 break;
             case NEU_TYPE_INT32:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.i32;
                 break;
             case NEU_TYPE_INT64:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.i64;
                 break;
             case NEU_TYPE_WORD:
             case NEU_TYPE_UINT16:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.u16;
                 break;
             case NEU_TYPE_DWORD:
             case NEU_TYPE_UINT32:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.u32;
                 break;
             case NEU_TYPE_LWORD:
             case NEU_TYPE_UINT64:
                 json_tag->metas[k].t             = NEU_JSON_INT;
                 json_tag->metas[k].value.val_int = metas[k].value.value.u64;
                 break;
             case NEU_TYPE_FLOAT:
                 json_tag->metas[k].t               = NEU_JSON_FLOAT;
                 json_tag->metas[k].value.val_float = metas[k].value.value.f32;
                 break;
             case NEU_TYPE_DOUBLE:
                 json_tag->metas[k].t                = NEU_JSON_DOUBLE;
                 json_tag->metas[k].value.val_double = metas[k].value.value.d64;
                 break;
             case NEU_TYPE_BOOL:
                 json_tag->metas[k].t = NEU_JSON_BOOL;
                 json_tag->metas[k].value.val_bool =
                     metas[k].value.value.boolean;
                 break;
             case NEU_TYPE_BIT:
                 json_tag->metas[k].t             = NEU_JSON_BIT;
                 json_tag->metas[k].value.val_bit = metas[k].value.value.u8;
                 break;
             case NEU_TYPE_STRING:
             case NEU_TYPE_TIME:
             case NEU_TYPE_DATA_AND_TIME:
                 json_tag->metas[k].t             = NEU_JSON_STR;
                 json_tag->metas[k].value.val_str = metas[k].value.value.str;
                 break;
             default:
                 break;
             }
         } else {
             break;
         }
     }
 }
 
 int neu_json_decode_write_gtags_req(char *                       buf,
                                     neu_json_write_gtags_req_t **result)
 {
     void *json_obj = neu_json_decode_new(buf);
     if (NULL == json_obj) {
         return -1;
     }
 
     int ret = neu_json_decode_write_gtags_req_json(json_obj, result);
     neu_json_decode_free(json_obj);
     return ret;
 }
 
 #include "utils/log.h"
 
 static int decode_write_gtags_req_json(void *                      json_obj,
                                        neu_json_write_gtags_req_t *req)
 {
     int ret = 0;
 
     neu_json_elem_t req_elems[] = {
         {
             .name = "node",
             .t    = NEU_JSON_STR,
         },
         {
             .name = "groups",
             .t    = NEU_JSON_OBJECT,
         },
     };
     ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems),
                                   req_elems);
     if (ret != 0) {
         return -1;
     }
 
     req->node = req_elems[0].v.val_str;
 
     req->n_group = neu_json_decode_array_size_by_json(json_obj, "groups");
     if (req->n_group <= 0) {
         return -1;
     }
 
     req->groups = calloc(req->n_group, sizeof(neu_json_write_gtags_elem_t));
     for (int i = 0; i < req->n_group; i++) {
         neu_json_elem_t g_elems[] = {
             {
                 .name = "group",
                 .t    = NEU_JSON_STR,
             },
             {
                 .name = "tags",
                 .t    = NEU_JSON_OBJECT,
             },
         };
 
         ret = neu_json_decode_array_by_json(
             json_obj, "groups", i, NEU_JSON_ELEM_SIZE(g_elems), g_elems);
 
         req->groups[i].group = g_elems[0].v.val_str;
         req->groups[i].n_tag = json_array_size(g_elems[1].v.val_object);
         if (req->groups[i].n_tag <= 0) {
             continue;
         }
 
         req->groups[i].tags =
             calloc(req->groups[i].n_tag, sizeof(neu_json_write_tags_elem_t));
 
         for (int k = 0; k < req->groups[i].n_tag; k++) {
             neu_json_elem_t v_elems[] = {
                 {
                     .name = "tag",
                     .t    = NEU_JSON_STR,
                 },
                 {
                     .name = "value",
                     .t    = NEU_JSON_VALUE,
                 },
             };
 
             ret = neu_json_decode_array_elem(g_elems[1].v.val_object, k,
                                              NEU_JSON_ELEM_SIZE(v_elems),
                                              v_elems);
             if (ret != 0) {
                 for (int x = i; x >= 0; x--) {
                     free(req->groups[x].tags);
                 }
                 free(req->groups);
                 return -1;
             }
             req->groups[i].tags[k].tag   = v_elems[0].v.val_str;
             req->groups[i].tags[k].t     = v_elems[1].t;
             req->groups[i].tags[k].value = v_elems[1].v;
         }
     }
 
     return 0;
 }
 
 int neu_json_decode_write_gtags_req_json(void *                       json_obj,
                                          neu_json_write_gtags_req_t **result)
 {
     neu_json_write_gtags_req_t *req =
         calloc(1, sizeof(neu_json_write_gtags_req_t));
     if (req == NULL) {
         return -1;
     }
 
     int ret = decode_write_gtags_req_json(json_obj, req);
     if (0 == ret) {
         *result = req;
     } else {
         free(req);
     }
 
     return ret;
 }
 
 void neu_json_decode_write_gtags_req_free(neu_json_write_gtags_req_t *req)
 {
     free(req->node);
 
     for (int i = 0; i < req->n_group; i++) {
         free(req->groups[i].group);
 
         for (int k = 0; k < req->groups[i].n_tag; k++) {
             free(req->groups[i].tags[k].tag);
 
             if (req->groups[i].tags[k].t == NEU_JSON_STR) {
                 free(req->groups[i].tags[k].value.val_str);
             }
             if (req->groups[i].tags[k].t == NEU_JSON_ARRAY_INT8 &&
                 req->groups[i].tags[k].value.val_array_int8.length > 0) {
                 free(req->groups[i].tags[k].value.val_array_int8.i8s);
             }
             if (req->groups[i].tags[k].t == NEU_JSON_ARRAY_UINT8 &&
                 req->groups[i].tags[k].value.val_array_uint8.length > 0) {
                 free(req->groups[i].tags[k].value.val_array_uint8.u8s);
             }
             if (req->groups[i].tags[k].t == NEU_JSON_ARRAY_INT16 &&
                 req->groups[i].tags[k].value.val_array_int16.length > 0) {
                 free(req->groups[i].tags[k].value.val_array_int16.i16s);
             }
             if (req->groups[i].tags[k].t == NEU_JSON_ARRAY_UINT16 &&
                 req->groups[i].tags[k].value.val_array_uint16.length > 0) {
                 free(req->groups[i].tags[k].value.val_array_uint16.u16s);
             }
             if (req->groups[i].tags[k].t == NEU_JSON_ARRAY_INT32 &&
                 req->groups[i].tags[k].value.val_array_int32.length > 0) {
                 free(req->groups[i].tags[k].value.val_array_int32.i32s);
             }
             if (req->groups[i].tags[k].t == NEU_JSON_ARRAY_UINT32 &&
                 req->groups[i].tags[k].value.val_array_uint32.length > 0) {
                 free(req->groups[i].tags[k].value.val_array_uint32.u32s);
             }
             if (req->groups[i].tags[k].t == NEU_JSON_ARRAY_INT64 &&
                 req->groups[i].tags[k].value.val_array_int64.length > 0) {
                 free(req->groups[i].tags[k].value.val_array_int64.i64s);
             }
             if (req->groups[i].tags[k].t == NEU_JSON_ARRAY_UINT64 &&
                 req->groups[i].tags[k].value.val_array_uint64.length > 0) {
                 free(req->groups[i].tags[k].value.val_array_uint64.u64s);
             }
             if (req->groups[i].tags[k].t == NEU_JSON_ARRAY_FLOAT &&
                 req->groups[i].tags[k].value.val_array_float.length > 0) {
                 free(req->groups[i].tags[k].value.val_array_float.f32s);
             }
             if (req->groups[i].tags[k].t == NEU_JSON_ARRAY_DOUBLE &&
                 req->groups[i].tags[k].value.val_array_double.length > 0) {
                 free(req->groups[i].tags[k].value.val_array_double.f64s);
             }
             if (req->groups[i].tags[k].t == NEU_JSON_ARRAY_BOOL &&
                 req->groups[i].tags[k].value.val_array_bool.length > 0) {
                 free(req->groups[i].tags[k].value.val_array_bool.bools);
             }
         }
         if (req->groups[i].n_tag > 0) {
             free(req->groups[i].tags);
         }
     }
 
     free(req->groups);
     free(req);
 }
 